/**龙兄弟锁具 */
const CryptoJS = require('./crypto-js.js');
export default class BluetoothLock_lxd_a {//龙兄弟a版协议

  constructor(deviceId,aesKey,pwdBytes) {
    // AES-128密钥 (示例密钥，实际应用时请替换)
//     this.aesKey = [0x57, 0x61, 0x6C, 0x6B, 0x69, 0x7A, 0x35, 0x32, 0x38, 0x33, 0x32, 0x69, 0x4C, 0x6F, 0x63, 0x6B];
//     this.pwdBytes=[0x31,0x31,0x30,0x30,0x36,0x34];
// 中间版---
    // this.aesKey = [0x3B, 0x37, 0x0F, 0x8D, 0xBD, 0xFD, 0x5C, 0x03, 0xB6, 0x1C, 0x17, 0x1B, 0x43, 0x67, 0x20, 0xF0];
    // this.pwdBytes=[0x00,0x0F,0x82,0xEB,0x6A,0x40];
// 新进锁200-1
    // this.aesKey = [0xB5, 0x09, 0xC9, 0x86, 0xEC, 0xC0, 0xAF, 0x02, 0x22, 0xB6, 0xE1, 0x0E, 0x02, 0xCA, 0x74, 0xFC];
    // this.pwdBytes=[0x9A,0x44,0xA7,0xA5,0xD6,0xCA];
    this.aesKey = aesKey;
    this.pwdBytes=pwdBytes;
    this.serviceId="00008000-0000-1000-8000-57616C6B697A";//服务id
    this.characteristicId="00008001-0000-1000-8000-57616C6B697A";//写 特征值
    this.wcharacteristicId="00008002-0000-1000-8000-57616C6B697A";//读 特征值

    //搜索到设备并连接后，需要注入这些值
    this.deviceId=deviceId;//设备deviceId

  }
  // ====== 解析类 ======
  /**
   * 统一解析蓝牙收到的响应
   * @param {Uint8Array} response - 蓝牙设备返回的响应数据 
   * @returns {Object} - 解析后的结果
   */
    /**
   * 统一解析蓝牙响应
   * @param {Uint8Array} response - 蓝牙设备返回的响应数据
   * @returns {Object} - 解析后的结果
   */
  parseBluetoothResponse(response) {
    const encryptedDataHex = this.uint8ArraytoHexString(response);

    if (response.length < 16) {
      console.log("收到广播数据", this.uint8ArraytoHexString(response));
      this.parseBroadcastData(encryptedDataHex);
      return;
    }
    
    const decryptedDataBytes = this.hexStringToBytes(this.aesDecrypt(encryptedDataHex));

    const command = decryptedDataBytes[0];  // 命令字节
    const subCommand = decryptedDataBytes[1];  // 子命令字节

    // 根据命令字节和子命令字节分配解析函数
    switch (command) {
        // 获取令牌响应，协议编号 2.1.1
        case 0xFC:  
            if (subCommand === 0x00) {
                return this.parseTokenResponse(encryptedDataHex); // 解析获取令牌的响应
            }
            break;

        // 查询设备系统时间响应，协议编号 2.2.2
        case 0xEF:  
            if (subCommand === 0x01) {
                return this.parseSystemTimeResponse(encryptedDataHex); // 解析查询设备系统时间的响应
            }
            break;

        // 获取电量响应，协议编号 2.2.3
        case 0xEE:  
            if (subCommand === 0x00) {
                return this.parseBatteryResponse(encryptedDataHex); // 解析获取电量的响应
            }
            break;

        // 开锁/关锁/上锁状态，协议编号 2.3.1，2.3.2，2.3.3，2.3.4
        case 0xDF:  
            switch (subCommand) {
                case 0x00:
                    return this.parseUnlockResponse(encryptedDataHex); // 解析开锁响应 (2.3.1)
                case 0x01:
                    return this.parseLockResponse(encryptedDataHex); // 解析关锁响应 (2.3.2)
                case 0x02:
                    return this.parseAutoLockResponse(encryptedDataHex); // 解析上锁响应 (2.3.3)
                case 0x03:
                    return this.parseQueryLockStatusResponse(encryptedDataHex); // 解析锁状态响应 (2.3.4)
            }
            break;

        // 系统复位/恢复出厂设置响应，协议编号 2.3.5，2.3.6
        case 0xDE:  
            switch (subCommand) {
                case 0x00:
                    return this.parseSystemResetResponse(encryptedDataHex); // 解析系统复位响应 (2.3.5)
                case 0x01:
                    return this.parseFactoryResetResponse(encryptedDataHex); // 解析恢复出厂设置响应 (2.3.6)
            }
            break;

        // 查询指纹相关操作，协议编号 2.4.x
        case 0xCF:  
            switch (subCommand) {
                case 0x00:
                    return this.parseFingerprintCountResponse(encryptedDataHex); // 解析查询指纹数量响应 (2.4.1)
                case 0x01:
                    return this.parseFingerprintInfoResponse(encryptedDataHex); // 解析查询指纹响应 (2.4.2)
                case 0x03:
                    return this.parseFingerprintRegisterResponse(encryptedDataHex); // 解析指纹注册响应 (2.4.3)
                case 0x04:
                    return this.parseCancelFingerprintRegisterResponse(encryptedDataHex); // 解析取消指纹注册响应 (2.4.4)
                case 0x06:
                    return this.parseDeleteFingerprintResponse(encryptedDataHex); // 解析删除指纹响应 (2.4.5)
                case 0x07:
                    return this.parseVerifyFingerprintResponse(encryptedDataHex); // 解析校准指纹响应 (2.4.6)
                case 0x09:
                    return this.parseFingerprintRecordIDsResponse(encryptedDataHex); // 解析获取已录入指纹ID响应 (2.4.7)
            }
            break;

        // 固件升级响应，协议编号 2.5.x
        case 0xBF:  
            switch (subCommand) {
                case 0x01:
                    return this.parseFirmwareUpgradeResultResponse(encryptedDataHex); // 解析蓝牙反馈升级结果 (2.5.2)
                case 0x02:
                    return this.parseFirmwareUpgradePacketRequest(encryptedDataHex); // 解析锁申请固件包 (2.5.3)
            }
            break;

        // 开锁记录相关操作，协议编号 2.7.x
        case 0x9F:  
            switch (subCommand) {
                case 0x00:
                    return this.parseUnlockRecordCountResponse(encryptedDataHex); // 解析开锁记录数量响应 (2.7.1)
                case 0x01:
                    return this.parseUnlockRecordDataResponse(encryptedDataHex); // 解析获取开锁记录数据响应 (2.7.2)
                case 0x03:
                    return this.parseClearUnlockRecordResponse(encryptedDataHex); // 解析清除开锁记录响应 (2.7.3)
                case 0x06:
                    return this.parseSyncUnlockRecordResponse(encryptedDataHex); // 解析自动同步开锁记录响应 (2.7.4)
            }
            break;

        default:
            throw new Error(`未知的命令字节: ${command}`);
    }
  }

    /**
     * 2.1.1 获取令牌
   * 发送获取令牌的请求
   * 根据协议文档，发送获取令牌的指令是通过指定的命令字节来完成的。
   * 该命令用于从蓝牙锁中获取令牌，该令牌用于后续的通信验证。
   * 
   * @example
   * lock.getToken(); // 发送获取令牌请求
   */
  getToken() {
    // 获取令牌的命令 (03 00) 后面填充14字节 0x00
    const command = [0x03, 0x00];  // 获取令牌的指令
    const data = new Array(14).fill(0x00);  // 填充0x00

    // 构建16字节的通信帧
    let frame = this.buildFrame(command, data);

    // 加密通信帧
    let encryptedFrame = this.aesEncrypt(frame);

    // 发送加密的帧到锁设备
    this.sendToLock(encryptedFrame);
  }

    /**
     * 2.1.1 获取令牌
   * 解析获取令牌的响应
   * 该函数用于解析蓝牙设备返回的加密数据，提取出令牌以及锁的状态、电压、电池电量等信息。
   * 
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串) 
   * @returns {Object} - 解析后的数据，包括令牌、MD、SD、VER、LVL、FVER、MODE、N等信息
   * @example
   * const tokenInfo = lock.parseTokenResponse('1a2b3c4d...');
   * console.log(tokenInfo); // { token: '...', md: '...', sd: '...', ver: '...' ...}
   */
  parseTokenResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是获取令牌的响应 (命令字节应为 0xFC 和 0x00)
    if (decryptedData[0] === 0xFC && decryptedData[1] === 0x00) {
        const token = decryptedData.slice(2, 6);  // 提取4字节的令牌
        const md = decryptedData[6];  // MD: 产品ID
        const sd = decryptedData[7];  // SD: 产品区分ID
        const ver = decryptedData.slice(8, 10);  // 版本号（2字节）
        const lvl = decryptedData[10];  // LVL: 当前电量
        const fver = decryptedData[11];  // FVER: 固件版本号
        const mode = decryptedData[12];  // MODE: 产品类型编号
        const n = decryptedData[13];  // N: 开锁记录数量

        var lockToken =this.uint8ArraytoHexString(token);
        wx.setStorageSync('lockToken',lockToken);

        return {
            token: lockToken,  // 返回令牌（HEX格式）
            md: md,  // 产品ID
            sd: sd,  // 产品区分ID
            ver: this.uint8ArraytoHexString(ver),  // 版本号
            lvl: lvl,  // 当前电量
            fver: fver,  // 固件版本号
            mode: mode,  // 产品类型编号
            n: n  // 开锁记录数量
        };
    } else {
        throw new Error('无效的令牌响应');
    }
  }

  /**
   * 2.2.1 同步日期时间
   * 发送同步日期时间的请求
   * 该函数用于将当前的日期时间（以秒为单位）发送到蓝牙锁进行同步。
   *
   * @example
   * lock.syncDateTime(); // 同步当前日期和时间
   */
  syncDateTime() {
    // 获取当前时间戳，单位为秒 (从 1970 年 1 月 1 日以来的秒数)
    const currentTimeInSeconds = Math.floor(Date.now() / 1000); 

    // 将时间戳转换为4字节小端字节序
    const timeBytes = [
        currentTimeInSeconds & 0xFF,
        (currentTimeInSeconds >> 8) & 0xFF,
        (currentTimeInSeconds >> 16) & 0xFF,
        (currentTimeInSeconds >> 24) & 0xFF
    ];

    // 同步时间的指令 (04 01)
    const command = [0x04, 0x01];  
    const data = timeBytes;  // 填充当前时间数据

    // 构建16字节的通信帧
    let frame = this.buildFrame(command, data);

    // 加密通信帧
    let encryptedFrame = this.aesEncrypt(frame);

    // 发送加密的帧到锁设备
    this.sendToLock(encryptedFrame);
  }

  /**
   * 2.2.1 同步日期时间
   * 解析同步日期时间的响应
   * 该函数用于解析蓝牙锁返回的同步时间的响应数据。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的数据，包括锁的产品ID、版本号、电量、模式等信息
   * @example
   * const syncInfo = lock.parseSyncDateTimeResponse('1a2b3c4d...');
   * console.log(syncInfo); // { md: '...', sd: '...', ver: '...' ... }
   */
  parseSyncDateTimeResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是同步时间的响应 (命令字节应为 0xFC 和 0x01)
    if (decryptedData[0] === 0xFC && decryptedData[1] === 0x01) {
        const md = decryptedData[2];  // MD: 产品ID
        const sd = decryptedData[3];  // SD: 产品区分ID
        const ver = decryptedData.slice(4, 6);  // 版本号（2字节）
        const lvl = decryptedData[6];  // LVL: 当前电量
        const fver = decryptedData[7];  // FVER: 固件版本号
        const mode = decryptedData[8];  // MODE: 产品类型编号
        const n = decryptedData[9];  // N: 开锁记录数量

        return {
            md: md,  // 产品ID
            sd: sd,  // 产品区分ID
            ver: this.uint8ArraytoHexString(ver),  // 版本号
            lvl: lvl,  // 当前电量
            fver: fver,  // 固件版本号
            mode: mode,  // 产品类型编号
            n: n  // 开锁记录数量
        };
    } else {
        throw new Error('无效的同步日期时间响应');
    }
  }


  /**
   * 2.2.2 查询设备系统时间
   * 发送查询设备系统时间的请求
   * 该函数用于向蓝牙锁发送查询系统时间的请求。
   *
   * @param {string} token - 4字节的令牌 (HEX string) 例如：'1a2b3c4d'
   * @example
   * lock.queryDeviceSystemTime('1a2b3c4d'); // 发送查询设备系统时间的请求
   */
  queryDeviceSystemTime(token) {
    // 查询设备系统时间的命令 (10 01)
    const command = [0x10, 0x01];

    // 将令牌转换为字节数组，并添加到数据中
    const tokenBytes = this.hexStringToBytes(token);
    const data = [...Array(10).fill(0x00), ...tokenBytes]; // 10个0x00填充 + 4字节令牌

    // 构建16字节的通信帧
    let frame = this.buildFrame(command, data);

    // 加密通信帧
    let encryptedFrame = this.aesEncrypt(frame);

    // 发送加密的帧到锁设备
    this.sendToLock(encryptedFrame);
  }
  /**
   * 2.2.2 查询设备系统时间
   * 解析查询设备系统时间的响应
   * 该函数用于解析蓝牙锁返回的系统时间响应数据。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的系统时间信息，包括年、月、日、时、分、秒等
   * @example
   * const timeResult = lock.parseDeviceSystemTimeResponse('1a2b3c4d...');
   * console.log(timeResult); // { success: true, year: 2019, month: 12, day: 25, hour: 15, minute: 30, second: 45 }
   */
  parseDeviceSystemTimeResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是查询设备系统时间的响应 (命令字节应为 0xEF 和 0x01)
    if (decryptedData[0] === 0xEF && decryptedData[1] === 0x01) {
        const or = decryptedData[2];  // OR: 操作结果

        if (or === 0x00) { // 操作结果成功
            const year = 2000 + decryptedData[3];  // 年份 = 2000 + YR
            const month = decryptedData[4];  // 月
            const day = decryptedData[5];    // 日
            const hour = decryptedData[6];   // 小时
            const minute = decryptedData[7]; // 分钟
            const second = decryptedData[8]; // 秒

            return {
                success: true,
                year: year,
                month: month,
                day: day,
                hour: hour,
                minute: minute,
                second: second
            };
        } else {
            return { success: false, message: '查询设备系统时间失败' };
        }
    } else {
        throw new Error('无效的查询设备系统时间响应');
    }
  }
  /**
   * 2.2.3 获取电量
   * 发送获取电量的请求
   * 该函数用于向蓝牙锁发送获取当前电量和电压的请求。
   *
   * @param {string} token - 4字节的令牌 (HEX string) 例如：'1a2b3c4d'
   * @example
   * lock.getBatteryLevel('1a2b3c4d'); // 发送获取电量请求
   */
  getBatteryLevel(token) {
    // 获取电量的命令 (11 00)
    const command = [0x11, 0x00];

    // 将令牌转换为字节数组，并添加到数据中
    const tokenBytes = this.hexStringToBytes(token);
    const data = [...Array(10).fill(0x00), ...tokenBytes]; // 10个0x00填充 + 4字节令牌

    // 构建16字节的通信帧
    let frame = this.buildFrame(command, data);

    // 加密通信帧
    let encryptedFrame = this.aesEncrypt(frame);

    // 发送加密的帧到锁设备
    this.sendToLock(encryptedFrame);
  }
  /**
   * 2.2.3 获取电量
   * 解析获取电量的响应
   * 该函数用于解析蓝牙锁返回的电量和电压信息。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的电量和电压信息
   * @example
   * const batteryInfo = lock.parseBatteryLevelResponse('1a2b3c4d...');
   * console.log(batteryInfo); // { success: true, level: 85, voltage: 3.7 }
   */
  parseBatteryLevelResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是获取电量的响应 (命令字节应为 0xEE 和 0x00)
    if (decryptedData[0] === 0xEE && decryptedData[1] === 0x00) {
        const level = decryptedData[2];  // LVL: 当前电量，1字节
        const voltage = ((decryptedData[3] << 8) | decryptedData[4]) / 100;  // VOL: 当前电压，2字节，单位为0.01V

        return {
            success: true,
            level: level,       // 电量百分比
            voltage: voltage    // 电压（单位V）
        };
    } else {
        return { success: false, message: '获取电量失败' };
    }
  }

  /**
   * 2.3.1 开锁
   * 发送开锁请求
   * 该函数用于向蓝牙锁发送开锁请求。
   *
   * @param {string} password - 6位的开锁密码 (如 "123456")
   * @param {string} sn - 4字节的开锁流水号 (HEX 字符串)
   * @param {string} token - 4字节的令牌 (HEX 字符串)
   * @example
   * lock.unlock('123456', '00112233', 'aabbccdd');
   */
  unlock(sn, token) {
    // 校验密码长度为6位
    if (this.pwdBytes.length !== 6) {
        throw new Error('密码必须为6位数字');
    }

    // 将密码和流水号、令牌转换为字节数组
    // const pwdBytes = this.stringToBytes(password);
    const pwdBytes = this.pwdBytes;
    const snBytes = this.hexStringToBytes(sn);
    const tokenBytes = this.hexStringToBytes(token);

    // 构建通信帧数据，密码(6字节) + 流水号(4字节) + 令牌(4字节)
    const command = [0x20, 0x00];
    const data = [...pwdBytes, ...snBytes, ...tokenBytes];
    console.log(data)
    // 构建16字节通信帧
    let frame = this.buildFrame(command, data);

    // 加密通信帧
    let encryptedFrame = this.aesEncrypt(frame);

    // 发送加密的帧到锁设备
    this.sendToLock(encryptedFrame);
  }

  /**
   * 2.3.1 开锁
   * 解析开锁响应
   * 该函数用于解析蓝牙锁返回的开锁结果。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的开锁结果
   * @example
   * const unlockResult = lock.parseUnlockResponse('aabbccdd...');
   * console.log(unlockResult); // { success: true, message: '开锁成功' }
   */
  parseUnlockResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是开锁的响应 (命令字节应为 0xDF 和 0x00)
    if (decryptedData[0] === 0xDF && decryptedData[1] === 0x00) {
        const operationResult = decryptedData[2]; // OR 操作结果
        const sn = decryptedData.slice(3, 7); // SN: 开锁流水号

        // 根据操作结果返回不同的状态
        if (operationResult === 0x00) {
            return { success: true, message: '开锁成功', sn: this.uint8ArraytoHexString(sn) };
        } else if (operationResult === 0x01) {
            return { success: false, message: '密码不匹配', sn: this.uint8ArraytoHexString(sn) };
        } else {
            return { success: false, message: '开锁失败', sn: this.uint8ArraytoHexString(sn) };
        }
    } else {
        return { success: false, message: '无效的开锁响应' };
    }
  }

  /**
   * 2.3.2 关锁 
   * 发送关锁请求
   * 该函数用于向蓝牙锁发送关锁请求。
   *
   * @param {string} token - 4字节的令牌 (HEX 字符串)
   * @example
   * lock.lock('aabbccdd');
   */
  lock(token) {
    // 将令牌转换为字节数组
    const tokenBytes = this.hexStringToBytes(token);

    // 构建通信帧数据
    const command = [0x20, 0x01];
    const data = [...new Array(10).fill(0x00), ...tokenBytes]; // 10字节填充 + 令牌

    // 构建16字节通信帧
    let frame = this.buildFrame(command, data);

    // 加密通信帧
    let encryptedFrame = this.aesEncrypt(frame);

    // 发送加密的帧到锁设备
    this.sendToLock(encryptedFrame);
  }

  /**
   * 2.3.2 关锁 
   * 解析关锁响应
   * 该函数用于解析蓝牙锁返回的关锁结果。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的关锁结果
   * @example
   * const lockResult = lock.parseLockResponse('aabbccdd...');
   * console.log(lockResult); // { success: true, message: '关锁成功' }
   */
  parseLockResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是关锁的响应 (命令字节应为 0xDF 和 0x01)
    if (decryptedData[0] === 0xDF && decryptedData[1] === 0x01) {
        const operationResult = decryptedData[2]; // OR 操作结果

        // 根据操作结果返回不同的状态
        if (operationResult === 0x00) {
            return { success: true, message: '关锁成功' };
        } else {
            return { success: false, message: '关锁失败' };
        }
    } else {
        return { success: false, message: '无效的关锁响应' };
    }
  }
  /**
   * 2.3.3 上锁
   * 解析上锁响应
   * 该函数用于解析锁设备在手动上锁后返回的通信帧。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的上锁结果
   * @example
   * const lockResult = lock.parseManualLockResponse('aabbccdd...');
   * console.log(lockResult); // { success: true, message: '上锁成功', sn: '00112233' }
   */
  parseManualLockResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是上锁的响应 (命令字节应为 0xDF 和 0x02)
    if (decryptedData[0] === 0xDF && decryptedData[1] === 0x02) {
        const operationResult = decryptedData[2]; // OR 操作结果
        const sn = decryptedData.slice(3, 7); // 获取SN (4字节)

        // 根据操作结果返回不同的状态
        if (operationResult === 0x00) {
            return {
                success: true,
                message: '上锁成功',
                sn: this.uint8ArraytoHexString(sn), // 将SN转换为HEX字符串
            };
        } else {
            return {
                success: false,
                message: '上锁失败',
                sn: this.uint8ArraytoHexString(sn), // 返回SN
            };
        }
    } else {
        return { success: false, message: '无效的上锁响应' };
    }
  }

  /**
   *  2.3.4 查询锁状态
   * 构建并发送查询锁状态的请求
   * 该函数用于构建查询锁状态的通信帧，并将其发送到蓝牙锁设备。
   * 
   * @param {string} token - 设备的TOKEN值，16进制字符串 (例如 '1a2b3c4d')
   * @returns {void}
   * @example
   * lock.queryLockStatus('1a2b3c4d');
   */
  queryLockStatus(token) {
    const command = [0x20, 0x03];  // 主机发送的命令前缀
    const tokenBytes = this.hexStringToBytes(token); // 将TOKEN转换为字节数组

    const frameData = [...Array(10).fill(0), ...tokenBytes];  // 填充FREE部分为0x00
    let frame = this.buildFrame(command, frameData);  // 构建16字节的数据帧
    let encryptedFrame = this.aesEncrypt(frame);      // 对数据帧进行AES加密
    this.sendToLock(encryptedFrame);                  // 发送加密后的通信帧
  }

  /**
   *  2.3.4 查询锁状态
   * 解析查询锁状态的响应
   * 该函数用于解析锁设备返回的查询锁状态通信帧。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的锁状态和电平信息
   * @example
   * const lockStatus = lock.parseQueryLockStatusResponse('aabbccdd...');
   * console.log(lockStatus); // { locked: true, highLevel: true }
   */
  parseQueryLockStatusResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是查询锁状态的响应 (命令字节应为 0xDF 和 0x03)
    if (decryptedData[0] === 0xDF && decryptedData[1] === 0x03) {
        const lockStatus = decryptedData[2]; // SW 锁状态
        const batteryLevel = decryptedData[3]; // LVL 电平状态

        // 解析锁状态：00表示锁是关闭的，01表示锁是打开的
        const locked = lockStatus === 0x00;

        // 解析电平状态：00表示低电平，01表示高电平
        const highLevel = batteryLevel === 0x01;

        return {
            locked: locked,
            highLevel: highLevel,
            message: `锁状态: ${locked ? '关闭' : '打开'}, 电平: ${highLevel ? '高电平' : '低电平'}`
        };
    } else {
        return { success: false, message: '无效的查询锁状态响应' };
    }
  }

  /**
   * 2.3.5 系统复位
   * 构建并发送系统复位的请求
   * 该函数用于构建系统复位的通信帧，并将其发送到蓝牙锁设备。
   * 
   * @param {string} token - 设备的TOKEN值，16进制字符串 (例如 '1a2b3c4d')
   * @returns {void}
   * @example
   * lock.systemReset('1a2b3c4d');
   */
  systemReset(token) {
    const command = [0x21, 0x00];  // 主机发送的命令前缀
    const tokenBytes = this.hexStringToBytes(token);  // 将TOKEN转换为字节数组

    // 填充FREE部分为0x00，并附加TOKEN
    const frameData = [...Array(10).fill(0), ...tokenBytes];
    let frame = this.buildFrame(command, frameData);  // 构建16字节的数据帧
    let encryptedFrame = this.aesEncrypt(frame);      // 对数据帧进行AES加密
    this.sendToLock(encryptedFrame);                  // 发送加密后的通信帧
  }


  /**
   * 2.3.5 系统复位
   * 解析系统复位的响应
   * 该函数用于解析锁设备返回的系统复位响应数据。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的系统复位结果
   * @example
   * const resetResult = lock.parseSystemResetResponse('aabbccdd...');
   * console.log(resetResult); // { success: true, message: '系统复位成功' }
   */
  parseSystemResetResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是系统复位的响应 (命令字节应为 0xDE 和 0x00)
    if (decryptedData[0] === 0xDE && decryptedData[1] === 0x00) {
        const operationResult = decryptedData[2];  // OR 操作结果

        return {
            success: operationResult === 0x00,  // 0x00 表示成功，其他值表示失败
            message: operationResult === 0x00 ? '系统复位成功' : '系统复位失败'
        };
    } else {
        return { success: false, message: '无效的系统复位响应' };
    }
  }
  /**
   * 2.3.6 恢复出厂设置
   * 构建并发送恢复出厂设置的请求
   * 该函数用于恢复锁设备到出厂状态，并解除设备与APP的绑定。
   * 
   * @param {string} token - 设备的TOKEN值，16进制字符串 (例如 '1a2b3c4d')
   * @returns {void}
   * @example
   * lock.restoreFactorySettings('1a2b3c4d');
   */
  restoreFactorySettings(token) {
    const command = [0x21, 0x01];  // 主机发送的命令前缀，表示恢复出厂设置请求
    const tokenBytes = this.hexStringToBytes(token);  // 将TOKEN转换为字节数组

    // 构建数据帧，填充FREE部分为0x00，并附加TOKEN
    const frameData = [...Array(10).fill(0), ...tokenBytes];
    let frame = this.buildFrame(command, frameData);  // 构建16字节的数据帧
    let encryptedFrame = this.aesEncrypt(frame);      // 对数据帧进行AES加密
    this.sendToLock(encryptedFrame);                  // 发送加密后的通信帧
  }

  /**
   * 2.3.6 恢复出厂设置
   * 解析恢复出厂设置的响应
   * 该函数用于解析锁设备返回的恢复出厂设置响应数据。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的恢复出厂设置结果
   * @example
   * const result = lock.parseRestoreFactorySettingsResponse('aabbccdd...');
   * console.log(result); // { success: true, message: '恢复出厂设置成功' }
   */
  parseRestoreFactorySettingsResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是恢复出厂设置的响应 (命令字节应为 0xDE 和 0x01)
    if (decryptedData[0] === 0xDE && decryptedData[1] === 0x01) {
        const operationResult = decryptedData[2];  // OR 操作结果

        return {
            success: operationResult === 0x00,  // 0x00 表示成功，其他值表示失败
            message: operationResult === 0x00 ? '恢复出厂设置成功' : '恢复出厂设置失败'
        };
    } else {
        return { success: false, message: '无效的恢复出厂设置响应' };
    }
  }

  /**
   * 2.4.1 查询指纹数
   * 构建并发送查询指纹数的请求
   * 该函数用于查询当前锁设备中已存储的指纹数量。
   *
   * @param {string} token - 设备的TOKEN值，16进制字符串 (例如 '1a2b3c4d')
   * @returns {void}
   * @example
   * lock.queryFingerprintCount('1a2b3c4d');
   */
  queryFingerprintCount(token) {
    const command = [0x30, 0x00];  // 主机发送的命令前缀，表示查询指纹数请求
    const tokenBytes = this.hexStringToBytes(token);  // 将TOKEN转换为字节数组

    // 构建数据帧，填充FREE部分为0x00，并附加TOKEN
    const frameData = [...Array(10).fill(0), ...tokenBytes];
    let frame = this.buildFrame(command, frameData);  // 构建16字节的数据帧
    let encryptedFrame = this.aesEncrypt(frame);      // 对数据帧进行AES加密
    this.sendToLock(encryptedFrame);                  // 发送加密后的通信帧
  }

  /**
   * 2.4.1 查询指纹数
   * 解析查询指纹数的响应
   * 该函数用于解析锁设备返回的指纹数量。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的指纹数量
   * @example
   * const result = lock.parseFingerprintCountResponse('aabbccdd...');
   * console.log(result); // { fingerprintCount: 5 }
   */
  parseFingerprintCountResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是查询指纹数的响应 (命令字节应为 0xCF 和 0x00)
    if (decryptedData[0] === 0xCF && decryptedData[1] === 0x00) {
        const fingerprintCount = (decryptedData[2] << 8) | decryptedData[3];  // 获取指纹数量 (2字节)

        return {
            fingerprintCount: fingerprintCount  // 返回解析出的指纹数量
        };
    } else {
        return { fingerprintCount: 0, message: '无效的查询指纹数响应' };
    }
  }

  /**
   * 2.4.2 查询指纹
   * 构建并发送查询指纹的请求
   * 该函数用于查询锁设备中特定序号的指纹详细信息。
   *
   * @param {number} fingerprintIndex - 指纹序号，整数类型 (例如 1 表示第一枚指纹)
   * @param {string} token - 设备的TOKEN值，16进制字符串 (例如 '1a2b3c4d')
   * @returns {void}
   * @example
   * lock.queryFingerprint(1, '1a2b3c4d');
   */
  queryFingerprint(fingerprintIndex, token) {
    const command = [0x30, 0x01];  // 主机发送的命令前缀，表示查询指纹请求
    const tokenBytes = this.hexStringToBytes(token);  // 将TOKEN转换为字节数组

    // 构建数据帧，填充NO部分为指纹序号，小端序列表示，并附加TOKEN
    const frameData = [fingerprintIndex, ...Array(8).fill(0), ...tokenBytes];
    let frame = this.buildFrame(command, frameData);  // 构建16字节的数据帧
    let encryptedFrame = this.aesEncrypt(frame);      // 对数据帧进行AES加密
    this.sendToLock(encryptedFrame);                  // 发送加密后的通信帧
  }

  /**
   * 2.4.2 查询指纹
   * 解析查询指纹的响应
   * 该函数用于解析锁设备返回的指定序号指纹的详细信息。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的指纹信息
   * @example
   * const result = lock.parseFingerprintResponse('aabbccdd...');
   * console.log(result); // { fingerprintIndex: 1, id: 1234, permission: 0, frozen: false }
   */
  parseFingerprintResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是查询指纹的响应 (命令字节应为 0xCF 和 0x01)
    if (decryptedData[0] === 0xCF && decryptedData[1] === 0x01) {
        const operationResult = decryptedData[2]; // 操作结果 OR，00 表示成功
        if (operationResult !== 0x00) {
            return { success: false, message: '操作失败' };
        }

        const fingerprintIndex = decryptedData[3];  // 指纹序号 (NO)
        const fingerprintId = (decryptedData[4] << 8) | decryptedData[5];  // 指纹ID (2字节)
        const permission = decryptedData[6] >> 6;  // 权限级别，前2位，0表示普通权限，3表示最高权限
        const frozen = (decryptedData[6] & 0x01) === 1;  // 是否冻结，第2位，0表示正常，1表示已冻结

        return {
            success: true,
            fingerprintIndex: fingerprintIndex,   // 指纹序号
            fingerprintId: fingerprintId,         // 指纹ID
            permission: permission,               // 权限级别 (0: 普通, 3: 最高)
            frozen: frozen                        // 是否冻结
        };
    } else {
        return { success: false, message: '无效的查询指纹响应' };
    }
  }

  /**
   * 2.4.3 注册指纹
   * 构建并发送注册指纹的请求
   * 该函数用于注册新指纹到锁设备。
   *
   * @param {number} fingerprintId - 指纹ID，整数类型，范围是 0x0001 到 0xFFFF (例如 0x0001 表示注册第一个指纹)
   * @param {string} token - 设备的TOKEN值，16进制字符串 (例如 '1a2b3c4d')
   * @returns {void}
   * @example
   * lock.registerFingerprint(0xFFFF, '1a2b3c4d');  // 传递 0xFFFF 让系统自动分配 ID
   */
  registerFingerprint(fingerprintId, token) {
    const command = [0x30, 0x03];  // 主机发送的命令前缀，表示注册指纹请求
    const tokenBytes = this.hexStringToBytes(token);  // 将TOKEN转换为字节数组

    // 构建数据帧，前2字节为指纹ID (小端表示)，然后8字节的填充 (FREE)，最后4字节TOKEN
    const idBytes = [(fingerprintId & 0xFF), (fingerprintId >> 8) & 0xFF];
    const frameData = [...idBytes, ...Array(8).fill(0), ...tokenBytes];
    
    let frame = this.buildFrame(command, frameData);  // 构建16字节的数据帧
    let encryptedFrame = this.aesEncrypt(frame);      // 对数据帧进行AES加密
    this.sendToLock(encryptedFrame);                  // 发送加密后的通信帧
  }

  /**
   * 2.4.3 注册指纹
   * 解析注册指纹的响应
   * 该函数用于解析锁设备返回的注册指纹结果。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的指纹注册结果
   * @example
   * const result = lock.parseRegisterFingerprintResponse('aabbccdd...');
   * console.log(result); // { success: true, message: '指纹注册成功', progress: 50 }
   */
  parseRegisterFingerprintResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是注册指纹的响应 (命令字节应为 0xCF 和 0x03)
    if (decryptedData[0] === 0xCF && decryptedData[1] === 0x03) {
        const operationResult = decryptedData[2]; // 操作结果 OR，00 表示成功

        // 处理操作失败的情况
        if (operationResult === 0x03) {
            return { success: false, message: '获取图形失败' };
        } else if (operationResult === 0x1E) {
            return { success: false, message: '注册错误' };
        } else if (operationResult === 0x24) {
            return { success: false, message: 'ID 超时' };
        } else if (operationResult === 0x26) {
            return { success: false, message: '其他原因注册失败' };
        } else if (operationResult === 0x00) {
            // 解析指纹进度数据
            const progress = decryptedData[8];  // PRO 进度百分比
            const fingerprintId = (decryptedData[4] << 8) | decryptedData[5]; // 小端表示的指纹ID
            const count = decryptedData[3]; // 指纹进度计数

            // 成功注册
            if (fingerprintId === 0xFE) {
                return { success: true, message: '存储已满', progress: progress };
            } else if (fingerprintId === 0xFF) {
                return { success: true, message: '指纹存储成功', progress: progress };
            }

            return {
                success: true,
                message: '指纹注册成功',
                fingerprintId: fingerprintId,  // 注册成功的指纹ID
                count: count,  // 指纹进度计数
                progress: progress  // 注册进度百分比
            };
        }
    } else {
        return { success: false, message: '无效的注册指纹响应' };
    }
  }

  /**
   * 2.4.4 取消指纹注册
   * 构建并发送取消指纹注册的请求
   * 该函数用于取消指纹注册的操作。
   *
   * @param {string} token - 设备的TOKEN值，16进制字符串 (例如 '1a2b3c4d')
   * @returns {void}
   * @example
   * lock.cancelFingerprintRegistration('1a2b3c4d');
   */
  cancelFingerprintRegistration(token) {
    const command = [0x30, 0x04];  // 主机发送的命令前缀，表示取消指纹注册请求
    const tokenBytes = this.hexStringToBytes(token);  // 将TOKEN转换为字节数组

    // 构建数据帧，10字节的填充 (FREE)，最后4字节TOKEN
    const frameData = [...Array(10).fill(0), ...tokenBytes];
    
    let frame = this.buildFrame(command, frameData);  // 构建16字节的数据帧
    let encryptedFrame = this.aesEncrypt(frame);      // 对数据帧进行AES加密
    this.sendToLock(encryptedFrame);                  // 发送加密后的通信帧
  }

  /**
   * 2.4.4 取消指纹注册
   * 解析取消指纹注册的响应
   * 该函数用于解析锁设备返回的取消指纹注册结果。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的取消指纹注册结果
   * @example
   * const result = lock.parseCancelFingerprintRegistrationResponse('aabbccdd...');
   * console.log(result); // { success: true, message: '取消指纹注册成功' }
   */
  parseCancelFingerprintRegistrationResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是取消指纹注册的响应 (命令字节应为 0xCF 和 0x04)
    if (decryptedData[0] === 0xCF && decryptedData[1] === 0x04) {
        const operationResult = decryptedData[2]; // 操作结果 OR，00 表示成功

        // 处理响应结果
        if (operationResult === 0x00) {
            return { success: true, message: '取消指纹注册成功' };
        } else {
            return { success: false, message: '取消指纹注册失败' };
        }
    } else {
        return { success: false, message: '无效的取消指纹注册响应' };
    }
  }

  /**
   * 2.4.5 删除指纹
   * 构建并发送删除指纹的请求
   * 该函数用于删除指纹，可以指定删除某个指纹，也可以删除所有指纹。
   *
   * @param {number} fingerprintId - 指纹ID，范围为 0x0000 - 0xFFFF；FFFF表示删除全部指纹
   * @param {string} password - 开锁密码，目前未启用，可以传入6位数字 (例如 "123456")
   * @param {string} token - 设备的TOKEN值，16进制字符串 (例如 '1a2b3c4d')
   * @returns {void}
   * @example
   * lock.deleteFingerprint(0x0001, '123456', '1a2b3c4d');
   * lock.deleteFingerprint(0xFFFF, '123456', '1a2b3c4d'); // 删除所有指纹
   */
  deleteFingerprint(fingerprintId, password, token) {
    const command = [0x30, 0x06];  // 主机发送的命令前缀，表示删除指纹请求
    const idBytes = this.intToBytes(fingerprintId, 2);  // 指纹ID转换为2字节
    const pwdBytes = this.pwdBytes;  // 密码转换为6字节
    const tokenBytes = this.hexStringToBytes(token);  // TOKEN转换为字节数组

    if (pwdBytes.length !== 6) {
        throw new Error('密码必须为6位数字');
    }

    // 构建数据帧，前面2字节指纹ID，6字节密码，后面2字节填充 (FREE)，最后4字节TOKEN
    const frameData = [...idBytes, ...pwdBytes, 0x00, 0x00, ...tokenBytes];
    
    let frame = this.buildFrame(command, frameData);  // 构建16字节的数据帧
    let encryptedFrame = this.aesEncrypt(frame);      // 对数据帧进行AES加密
    this.sendToLock(encryptedFrame);                  // 发送加密后的通信帧
  }

  /**
   * 2.4.5 删除指纹
   * 解析删除指纹的响应
   * 该函数用于解析锁设备返回的删除指纹结果。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的删除指纹结果
   * @example
   * const result = lock.parseDeleteFingerprintResponse('aabbccdd...');
   * console.log(result); // { success: true, id: 0x0001, message: '删除指纹成功' }
   */
  parseDeleteFingerprintResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是删除指纹的响应 (命令字节应为 0xCF 和 0x06)
    if (decryptedData[0] === 0xCF && decryptedData[1] === 0x06) {
        const operationResult = decryptedData[2]; // 操作结果 OR，00 表示成功
        const fingerprintId = (decryptedData[3] << 8) | decryptedData[4];  // 指纹ID

        // 处理响应结果
        if (operationResult === 0x00) {
            return { success: true, id: fingerprintId, message: '删除指纹成功' };
        } else if (operationResult === 0x01) {
            return { success: false, message: '密码不匹配' };
        } else {
            return { success: false, message: '删除指纹失败' };
        }
    } else {
        return { success: false, message: '无效的删除指纹响应' };
    }
  }

  /**
   * 2.4.6 校准指纹
   * 构建并发送校准指纹的请求
   * 该函数用于发送校准指纹的请求通信帧。
   *
   * @param {string} token - 设备的TOKEN值，16进制字符串 (例如 '1a2b3c4d')
   * @returns {void}
   * @example
   * lock.calibrateFingerprint('1a2b3c4d');
   */
  calibrateFingerprint(token) {
    const command = [0x30, 0x07];  // 主机发送的命令前缀，表示校准指纹请求
    const tokenBytes = this.hexStringToBytes(token);  // TOKEN转换为字节数组

    // 构建数据帧，前面10字节为空，最后4字节为TOKEN
    const frameData = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ...tokenBytes];
    
    let frame = this.buildFrame(command, frameData);  // 构建16字节的数据帧
    let encryptedFrame = this.aesEncrypt(frame);      // 对数据帧进行AES加密
    this.sendToLock(encryptedFrame);                  // 发送加密后的通信帧
  }

  /**
   * 2.4.6 校准指纹
   * 解析校准指纹的响应
   * 该函数用于解析锁设备返回的校准指纹结果。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的校准指纹结果
   * @example
   * const result = lock.parseCalibrateFingerprintResponse('aabbccdd...');
   * console.log(result); // { success: true, message: '校准指纹成功' }
   */
  parseCalibrateFingerprintResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是校准指纹的响应 (命令字节应为 0xCF 和 0x07)
    if (decryptedData[0] === 0xCF && decryptedData[1] === 0x07) {
        const operationResult = decryptedData[2]; // 操作结果 OR，00 表示成功

        // 处理响应结果
        if (operationResult === 0x00) {
            return { success: true, message: '校准指纹成功' };
        } else {
            return { success: false, message: '校准指纹失败' };
        }
    } else {
        return { success: false, message: '无效的校准指纹响应' };
    }
  }

  /**
   * 2.4.7 获取已录入指纹ID
   * 构建并发送获取已录入指纹ID的请求
   * 该函数用于发送获取已录入指纹ID的请求通信帧。
   *
   * @param {string} token - 设备的TOKEN值，16进制字符串 (例如 '1a2b3c4d')
   * @returns {void}
   * @example
   * lock.getRegisteredFingerprintIDs('1a2b3c4d');
   */
  getRegisteredFingerprintIDs(token) {
    const command = [0x30, 0x09];  // 主机发送的命令前缀，表示获取已录入指纹ID请求
    const tokenBytes = this.hexStringToBytes(token);  // TOKEN转换为字节数组

    // 构建数据帧，前面10字节为空，最后4字节为TOKEN
    const frameData = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ...tokenBytes];
    
    let frame = this.buildFrame(command, frameData);  // 构建16字节的数据帧
    let encryptedFrame = this.aesEncrypt(frame);      // 对数据帧进行AES加密
    this.sendToLock(encryptedFrame);                  // 发送加密后的通信帧
  }

  /**
   * 2.4.7 获取已录入指纹ID
   * 解析获取已录入指纹ID的响应
   * 该函数用于解析锁设备返回的已录入指纹ID结果。
   *
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 解析后的已录入指纹ID结果
   * @example
   * const result = lock.parseRegisteredFingerprintIDsResponse('aabbccdd...');
   * console.log(result); // { success: true, ids: [1, 5, 6, 9, ...], message: '获取指纹ID成功' }
   */
  parseRegisteredFingerprintIDsResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是获取已录入指纹ID的响应 (命令字节应为 0xCF 和 0x09)
    if (decryptedData[0] === 0xCF && decryptedData[1] === 0x09) {
        const operationResult = decryptedData[2]; // 操作结果 OR，00 表示成功，01 表示失败

        // 如果操作成功，解析指纹ID位图
        if (operationResult === 0x00) {
            const ids = [];
            const idBitArray = decryptedData.slice(3, 16);  // 获取指纹ID位图的13个字节

            // 遍历每个字节，每一位代表一个指纹ID是否被占用
            for (let byteIndex = 0; byteIndex < idBitArray.length; byteIndex++) {
                const byte = idBitArray[byteIndex];
                for (let bitIndex = 0; bitIndex < 8; bitIndex++) {
                    if ((byte & (1 << bitIndex)) !== 0) {
                        const id = byteIndex * 8 + bitIndex + 1;  // ID从1开始
                        ids.push(id);
                    }
                }
            }

            return { success: true, ids: ids, message: '获取指纹ID成功' };
        } else {
            return { success: false, message: '获取指纹ID失败' };
        }
    } else {
        return { success: false, message: '无效的获取指纹ID响应' };
    }
  }

  /**
   * 2.5.1 升级数字固件
   * 构建并发送升级数字固件的请求
   * 
   * @param {number} ver - 固件版本号 (1 字节) 例如：0x01
   * @param {number} len - 固件长度 (1 字节) 例如：0x1A
   * @param {number} dev - 设备类型 (1 字节) 例如：0x01 表示特定设备类型
   * @param {number} xor - XOR 校验值 (1 字节) 用于校验固件内容
   * @param {string} token - TOKEN 值，HEX 字符串 (例如 '1a2b3c4d')
   * @returns {void}
   * @example
   * lock.upgradeFirmware(0x01, 0x1A, 0x01, 0x5A, '1a2b3c4d');
   */
  upgradeFirmware(ver, len, dev, xor, token) {
    const command = [0x40, 0x00];  // 主机发送命令前缀 (表示升级固件请求)
    const tokenBytes = this.hexStringToBytes(token);  // 将 TOKEN 转换为字节数组

    // 构建数据帧，包含 VER, LEN, DEV, XOR 和 TOKEN
    const frameData = [ver, len, dev, xor, ...tokenBytes];

    let frame = this.buildFrame(command, frameData);  // 构建16字节的数据帧
    let encryptedFrame = this.aesEncrypt(frame);      // 对数据帧进行 AES 加密
    this.sendToLock(encryptedFrame);                  // 发送加密后的通信帧
  }

  /**
   * 2.5.1 升级数字固件
   * 解析升级数字固件的响应
   * 该函数用于解析锁设备返回的升级数字固件操作结果。
   * 
   * @param {string} encryptedData - 锁返回的加密数据 (HEX 字符串)
   * @returns {Object} - 包含升级操作的结果
   * @example
   * const result = lock.parseUpgradeFirmwareResponse('aabbccdd...');
   * console.log(result); // { success: true, message: '设备准备升级' }
   */
  parseUpgradeFirmwareResponse(encryptedData) {
    // 解密返回的加密数据
    const decryptedData = this.hexStringToBytes(this.aesDecrypt(encryptedData));

    // 校验指令是否是升级数字固件的响应 (命令字节应为 0xBF)
    if (decryptedData[0] === 0xBF) {
        const operationResult = decryptedData[2]; // 操作结果 OR，00 表示成功，01 表示失败
        
        // 解析返回的操作结果
        if (operationResult === 0x00) {
            return { success: true, message: '设备准备升级' };
        } else if (operationResult === 0x01) {
            return { success: false, message: '设备检验失败' };
        } else if (operationResult === 0x02) {
            return { success: false, message: '设备类型不匹配' };
        } else if (operationResult === 0x03) {
            return { success: false, message: '固件文件长度错误' };
        } else {
            return { success: false, message: '未知的升级固件错误' };
        }
    } else {
        return { success: false, message: '无效的升级固件响应' };
    }
  }

  /**
   * 2.5.1 升级数字固件
   * 发送固件数据包
   * 
   * @param {Uint8Array} firmwareData - 固件文件的字节数组
   * @param {number} ver - 固件版本号 (2 字节)，例如：0x0101
   * @param {number} len - 固件文件长度 (2 字节)，单位：字节，例如：0x1A20
   * @param {number} dev - 设备类型 (1 字节)，例如：0x01
   * @param {number} xor - 固件文件的 XOR 校验值 (1 字节)，例如：0x5A
   * @returns {void}
   */
  async sendFirmwareChunks(firmwareData, ver, len, dev, xor) {
    const chunkSize = 16;  // 每个包的大小 16 字节
    const delayBetweenPackets = 10;  // 两个包之间的延时 (毫秒)
    const delayAfter1024Bytes = 300;  // 每发送 1024 字节后的延时 (毫秒)
    let totalSentBytes = 0;  // 已发送字节数

    for (let i = 0; i < firmwareData.length; i += chunkSize) {
        // 构建升级包：每包 16 字节
        const chunk = firmwareData.slice(i, i + chunkSize);

        // 计算校验值 XOR 并加入包中
        const fileChunk = [...chunk, (i === 0 ? ver >> 8 : ver & 0xff), len >> 8, len & 0xff, dev, xor];

        // 构建升级通信帧并加密
        const frame = this.buildFrame([0x41, 0x01], fileChunk);
        const encryptedFrame = this.aesEncrypt(frame);

        // 发送升级包到设备
        this.sendToLock(encryptedFrame);

        // 累加发送的字节数
        totalSentBytes += chunkSize;

        // 每发完 1024 字节，延迟 300ms
        if (totalSentBytes % 1024 === 0) {
            console.log('Sent 1024 bytes, delaying 300ms...');
            await this.delay(delayAfter1024Bytes);
        } else {
            // 每发送一个包后延时 10ms
            await this.delay(delayBetweenPackets);
        }
    }

    console.log('固件发送完成，等待设备验证...');
  }

  /**
  * 延迟函数 (用于异步操作中的等待)
  * @param {number} ms - 延迟的时间 (毫秒)
  * @returns {Promise<void>} - 返回一个 Promise, 表示延迟操作的完成
  */
  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 2.5.2 蓝牙反馈升级结果
   * 解析蓝牙反馈升级结果
   * @param {Uint8Array} response - 蓝牙设备返回的升级结果数据帧
   * @returns {Object} - 解析结果，包括操作结果和新的固件版本号
   * @example
   * const result = lock.parseUpgradeResult(response);
   * console.log(result);  // { success: true, version: '1.0.0' }
   */
  parseUpgradeResult(response) {
    const OR = response[1];  // 操作结果
    const verBytes = response.slice(3, 5);  // 固件版本号的字节
    const version = `${verBytes[0]}.${verBytes[1]}`;  // 将字节数组转化为版本号（如：'1.0'）

    return {
        success: OR === 0x00,
        OR: OR === 0x00 ? '升级成功' : (OR === 0x01 ? '校验失败' : '其他错误'),
        version: version
    };
  }

  /**
   * 2.5.3 锁申请固件包
   * 发送固件包响应 (明文传输)
   * @param {number} index - 当前升级包的序号，从 0 开始 (如: 0, 1, 2, ...)
   * @param {Uint8Array} pack - 固件包内容 (128 字节)
   * @returns {Uint8Array} - 构建的发送数据帧
   * @example
   * const responseFrame = lock.sendFirmwarePacket(0, new Uint8Array(128));
   * lock.sendToLock(responseFrame);
   */
  sendFirmwarePacket(index, pack) {
    if (pack.length !== 128) {
        throw new Error('固件包长度必须为128字节');
    }

    // 构建发送的帧 40 01 [Index] [Pack] [CHK]
    let frame = new Uint8Array(132);  // 固定长度为 132 字节
    frame[0] = 0x40;  // 固定值
    frame[1] = 0x01;  // 固定值
    frame[2] = index; // 升级包序号

    // 填充 Pack 数据部分
    for (let i = 0; i < 128; i++) {
        frame[3 + i] = pack[i];
    }

    // 计算 CHK 校验和 (BYTE0 到 BYTE131 的累加和)
    let checksum = 0;
    for (let i = 0; i < 131; i++) {
        checksum += frame[i];
    }
    frame[131] = checksum & 0xFF;  // 取最后一个字节的值

    return frame;
  }

  /**
   * 2.5.3 锁申请固件包
   * 解析锁申请固件包的请求
   * @param {Uint8Array} response - 锁主动发送的固件包请求数据帧
   * @returns {Object} - 返回解析后的包序号
   * @example
   * const request = lock.parseFirmwareRequest(response);
   * console.log(request.index);  // 输出包序号
   */
  parseFirmwareRequest(response) {
    if (response[0] !== 0xBF || response[1] !== 0x02) {
        throw new Error('无效的固件包请求帧');
    }

    const index = response[2];  // 固件包序号
    return {
        index: index
    };
  }

  /**
   * 2.7.1 查询开锁记录数量
   * 发送查询开锁记录数量的请求
   * @param {string} token - 4字节的令牌 (16进制字符串)
   * @returns {Uint8Array} - 构建的发送数据帧
   * @example
   * const frame = lock.sendUnlockRecordCountRequest('A1B2C3D4');
   * lock.sendToLock(frame);
   */
  sendUnlockRecordCountRequest(token) {
    const command = [0x60, 0x00];  // 查询开锁记录数量的命令
    const tokenBytes = this.hexStringToBytes(token);  // 将令牌转换为字节数组

    // 构建发送帧
    const frameData = [...Array(10).fill(0x00), ...tokenBytes];  // 填充空白和令牌
    let frame = this.buildFrame(command, frameData);  // 构建数据帧

    return frame;  // 返回构建好的帧
  }

  /**
   * 2.7.1 查询开锁记录数量
   * 解析查询开锁记录数量的响应
   * @param {Uint8Array} response - 锁返回的响应数据
   * @returns {Object} - 返回解析后的操作结果和记录数量
   * @example
   * const result = lock.parseUnlockRecordCountResponse(response);
   * console.log(result);
   */
  parseUnlockRecordCountResponse(response) {
    if (response[0] !== 0x9F || response[1] !== 0x00) {
        throw new Error('无效的查询开锁记录数量响应');
    }

    const operationResult = response[3];  // 操作结果
    const recordCount = response[4];  // 记录数量

    // 解析操作结果
    let resultMessage;
    if (operationResult === 0x00) {
        resultMessage = '查询成功';
    } else if (operationResult === 0x01) {
        resultMessage = '查询失败';
    } else {
        resultMessage = '未知操作结果';
    }

    return {
        success: operationResult === 0x00,  // 00表示成功，其他表示失败
        recordCount: recordCount,  // 开锁记录数量
        message: resultMessage
    };
  }

  /**
   * 2.7.2 获取开锁记录数据
   * 发送获取开锁记录数据的请求
   * @param {number} recordIndex - 要获取的记录索引 (0 ~ 126 或 0 ~ 101)
   * @param {string} token - 4字节的令牌 (16进制字符串)
   * @returns {Uint8Array} - 构建的发送数据帧
   * @example
   * const frame = lock.sendUnlockRecordDataRequest(1, 'A1B2C3D4');
   * lock.sendToLock(frame);
   */
  sendUnlockRecordDataRequest(recordIndex, token) {
    const command = [0x60, 0x01];  // 获取开锁记录数据的命令
    const tokenBytes = this.hexStringToBytes(token);  // 将令牌转换为字节数组

    // 构建发送帧
    const frameData = [recordIndex, ...Array(9).fill(0x00), ...tokenBytes];  // 填充记录索引、空白和令牌
    let frame = this.buildFrame(command, frameData);  // 构建数据帧

    return frame;  // 返回构建好的帧
  }

  /**
   * 2.7.2 获取开锁记录数据
   * 解析获取开锁记录数据的响应
   * @param {Uint8Array} response - 锁返回的响应数据
   * @returns {Object} - 返回解析后的开锁记录信息
   * @example
   * const result = lock.parseUnlockRecordDataResponse(response);
   * console.log(result);
   */
  parseUnlockRecordDataResponse(response) {
    if (response[0] !== 0x9F || response[1] !== 0x01) {
        throw new Error('无效的获取开锁记录数据响应');
    }

    const operationResult = response[3];  // 操作结果
    const unlockType = response[4];  // 开锁类型
    const userId = response[5];  // 用户ID
    const year = response[6] + 2000;  // 年 (2000 + byte value)
    const month = response[7];  // 月
    const day = response[8];  // 日
    const hour = response[9];  // 小时
    const minute = response[10];  // 分钟
    const second = response[11];  // 秒

    // 解析操作结果
    let resultMessage;
    if (operationResult === 0x00) {
        resultMessage = '获取记录成功';
    } else if (operationResult === 0x01) {
        resultMessage = '获取记录失败';
    } else {
        resultMessage = '未知操作结果';
    }

    return {
        success: operationResult === 0x00,  // 00表示成功，其他表示失败
        unlockType: unlockType,  // 开锁类型
        userId: userId,  // 用户ID
        timestamp: `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')} ${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}`,  // 格式化的时间戳
        message: resultMessage
    };
  }

  /**
   * 2.7.3 清除开锁记录
   * 发送清除开锁记录的请求
   * @param {number} num - 要清除的记录数，0xFFFF表示全部清除，其他值表示清除指定数量的记录
   * @param {string} token - 4字节的令牌 (16进制字符串)
   * @returns {Uint8Array} - 构建的发送数据帧
   * @example
   * const frame = lock.sendClearUnlockRecordRequest(0xFFFF, 'A1B2C3D4');
   * lock.sendToLock(frame);
   */
  sendClearUnlockRecordRequest(num, token) {
    const command = [0x60, 0x03];  // 清除开锁记录的命令
    const tokenBytes = this.hexStringToBytes(token);  // 将令牌转换为字节数组

    // 构建发送帧
    const frameData = [...this.intToBytes(num, 2), ...Array(8).fill(0x00), ...tokenBytes];  // 填充NUM、空白和令牌
    let frame = this.buildFrame(command, frameData);  // 构建数据帧

    return frame;  // 返回构建好的帧
  }

  /**
   * 2.7.3 清除开锁记录
   * 解析清除开锁记录的响应
   * @param {Uint8Array} response - 锁返回的响应数据
   * @returns {Object} - 返回解析结果，是否成功
   * @example
   * const result = lock.parseClearUnlockRecordResponse(response);
   * console.log(result);
   */
  parseClearUnlockRecordResponse(response) {
    if (response[0] !== 0x9F || response[1] !== 0x03) {
        throw new Error('无效的清除开锁记录响应');
    }

    const operationResult = response[2];  // 操作结果

    // 解析操作结果
    let resultMessage;
    if (operationResult === 0x00) {
        resultMessage = '清除记录成功';
    } else if (operationResult === 0x01) {
        resultMessage = '清除记录失败';
    } else {
        resultMessage = '未知操作结果';
    }

    return {
        success: operationResult === 0x00,  // 00表示成功，01表示失败
        message: resultMessage
    };
  }

  /**
   * 2.7.4 自动同步开锁记录
   * 发送同步开锁记录的请求
   * @param {number} N - 要获取的记录数量，一次最多获取20条。N>0 表示有数据，N=0 则表示没有数据
   * @param {string} token - 4字节的令牌 (16进制字符串)
   * @returns {Uint8Array} - 构建的发送数据帧
   * @example
   * const frame = lock.sendSyncUnlockRecordRequest(2, 'A1B2C3D4');
   * lock.sendToLock(frame);
   */
  sendSyncUnlockRecordRequest(N, token) {
    const command = [0x60, 0x06];  // 自动同步开锁记录的命令
    const tokenBytes = this.hexStringToBytes(token);  // 将令牌转换为字节数组

    // 构建发送帧
    const frameData = [N, ...Array(8).fill(0x00), ...tokenBytes];  // 填充N、空白和令牌
    let frame = this.buildFrame(command, frameData);  // 构建数据帧

    return frame;  // 返回构建好的帧
  }

  /**
   * 2.7.4 自动同步开锁记录
   * 解析自动同步开锁记录的响应
   * @param {Uint8Array} response - 锁返回的响应数据
   * @returns {Object} - 返回解析后的开锁记录
   * @example
   * const result = lock.parseSyncUnlockRecordResponse(response);
   * console.log(result);
   */
  parseSyncUnlockRecordResponse(response) {
    if (response[0] !== 0x9F || response[1] !== 0x06) {
        throw new Error('无效的同步开锁记录响应');
    }

    const N = response[2];  // N为开锁记录数量，N > 0 表示有数据

    let records = [];

    for (let i = 0; i < N; i++) {
        const offset = 3 + i * 10;  // 每条记录占用10字节
        const id = response[offset];  // 开锁记录ID
        const year = 2000 + response[offset + 1];  // 年份 (加2000)
        const month = response[offset + 2];  // 月份
        const day = response[offset + 3];  // 日期
        const hour = response[offset + 4];  // 小时
        const minute = response[offset + 5];  // 分钟
        const second = response[offset + 6];  // 秒
        const attribute = response[offset + 7];  // 属性 (权限、状态等)
        const serialNumber = (response[offset + 8] << 8) | response[offset + 9];  // 序号

        records.push({
            id: id,
            timestamp: `${year}-${month}-${day} ${hour}:${minute}:${second}`,
            attribute: this.parseRecordAttribute(attribute),
            serialNumber: serialNumber
        });
    }

    const checksum = response[203];  // 校验和
    const calculatedChecksum = this.calculateChecksum(response.slice(0, 202));

    if (checksum !== calculatedChecksum) {
        throw new Error('校验和不匹配，数据可能损坏');
    }

    return {
        recordCount: N,
        records: records,
        checksumValid: checksum === calculatedChecksum
    };
  }

  /**
  * 解析记录属性
  * @param {number} attribute - 属性字节
  * @returns {Object} - 解析后的属性对象
  */
  parseRecordAttribute(attribute) {
    const permissionLevel = (attribute & 0xC0) >> 6;  // 权限级别 (前2位)
    const frozen = (attribute & 0x20) !== 0;  // 冻结标志 (bit2)
    const unlockMethod = (attribute & 0x1C) >> 2;  // 开锁方式 (bit5,4,3)

    return {
        permissionLevel: permissionLevel === 0 ? '普通' : (permissionLevel === 3 ? '最高权限管理员' : '未知'),
        frozen: frozen,
        unlockMethod: this.getUnlockMethod(unlockMethod)
    };
  }

  /**
  * 根据位置信息获取开锁方式
  * @param {number} unlockMethod - 开锁方式位
  * @returns {string} - 开锁方式
  */
  getUnlockMethod(unlockMethod) {
    switch (unlockMethod) {
        case 0:
            return '指纹';
        case 1:
            return '密码';
        case 2:
            return '刷IC卡';
        case 4:
            return '远程通信';
        case 6:
            return '破坏';
        default:
            return '未知方式';
    }
  }

  /**
  * 计算校验和
  * @param {Uint8Array} data - 数据字节
  * @returns {number} - 校验和
  */
  calculateChecksum(data) {
    return data.reduce((sum, byte) => (sum + byte) & 0xFF, 0);
  }






  // ====== 通用方法 ======

  /**
   * AES-128加密
   * @param {Uint8Array} data - 要加密的数据
   * @returns {string} - 加密后的字符串 (Hex)
   */
  aesEncrypt(data) {
    // console.log("=======================aesEncrypt start")
    // console.log("key",this.uint8ArraytoHexString(this.aesKey))
    // console.log("data",this.uint8ArraytoHexString(data))
    const keyHex = CryptoJS.enc.Hex.parse(this.uint8ArraytoHexString(this.aesKey)); // 将密钥转换为16进制
    const dataHex = CryptoJS.enc.Hex.parse(this.uint8ArraytoHexString(data)); // 将数据转换为16进制
    const encrypted = CryptoJS.AES.encrypt(dataHex, keyHex, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.NoPadding
    });
    // console.log(encrypted.ciphertext.toString(CryptoJS.enc.Hex))
    // console.log("=======================aesEncrypt end")
    return encrypted.ciphertext.toString(CryptoJS.enc.Hex); // 返回加密结果
  }

/**
 * AES-128解密
 * @param {string} data - 加密的数据 (hex 字符串)
 * @returns {string} - 解密后的明文数据 (hex 字符串)
 */
aesDecrypt(data) {
  // console.log("=======================aesDecrypt start");

  // 将密钥转换为 Hex 格式
  const keyHex = CryptoJS.enc.Hex.parse(this.uint8ArraytoHexString(this.aesKey));
  // 将 data 转换为十六进制格式后进行解密
  let decrypted = CryptoJS.AES.decrypt(CryptoJS.lib.CipherParams.create({
    ciphertext: CryptoJS.enc.Hex.parse(data)
  }), keyHex, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.NoPadding
  });
  // 输出解密的原始数据 (Hex 格式)
  const decryptedHex = decrypted.toString(CryptoJS.enc.Hex);
  console.log("Decrypted (Hex):", decryptedHex);

  // console.log("=======================aesDecrypt end");

  // 返回解密后的数据 (Hex 格式)
  return decryptedHex;
}


/**
 * 构建通信帧 (16字节)
 * @param {Array<number>} command - 命令字节数组
 * @param {Array<number>} data - 需要填充的数据字节
 * @returns {Uint8Array} - 构建的16字节通信帧
 */
buildFrame(command, data) {
  // console.log("=======================buildFrame start")
  // 初始化16字节帧，未填充部分默认值为 0x00
  let frame = new Uint8Array(16);

  // 确保 command 的长度不超过16字节（防止溢出）
  if (command.length > 16) {
    throw new Error('Command length exceeds frame size');
  }

  // 先填入 command 部分
  for (let i = 0; i < command.length; i++) {
    frame[i] = command[i]; 
  }

  // 从 command.length 开始填充 data，确保总长度不超过 16 字节
  for (let i = 0; i < data.length && (i + command.length) < 16; i++) {
    frame[i + command.length] = data[i];
  }

  console.log("Frame:", this.uint8ArraytoHexString(frame));
  // console.log("=======================buildFrame end")
  return frame;
}


  /**
   * 发送数据到蓝牙锁 (模拟发送)
   * @param {hexstring} frame - 要发送的加密通信帧
   * @returns {void}
   */
  sendToLock(frame) {
    console.log(`Sending to lock via serviceId ${this.serviceId} and characteristic:`, this.characteristicId);
    wx.writeBLECharacteristicValue({
      deviceId: this.deviceId,
      serviceId: this.serviceId,
      characteristicId: this.characteristicId,
      value: this.hexStringToArrayBuffer(frame),
      success(res) {
          console.log('写入数据成功:', res);
      },
      fail(err) {
          console.log('写入数据失败:', err);
      },
      complete(res) {

      }
  });
  }

  /**
   * 将字符串转换为字节数组
   * @param {string} str - 需要转换的字符串
   * @returns {Array<number>} - 字节数组
   */
  stringToBytes(str) {
    let bytes = [];
    for (let i = 0; i < str.length; ++i) {
      bytes.push(str.charCodeAt(i)); // 将每个字符的编码转换为字节
    }
    return bytes;
  }

  /**
   * 将字节数组转换为16进制字符串
   * @param {Array<number>} byteArray - 字节数组
   * @returns {string} - 16进制字符串
   */
  arrayToHexString(byteArray) {
    return byteArray.map(b => ('00' + b.toString(16)).slice(-2)).join(''); // 每个字节转换为两位16进制
  }
  
  uint8ArraytoHexString(uint8Array) {
    return Array.from(uint8Array).map(byte => ('00' + byte.toString(16)).slice(-2)).join('');
  }

  /**
   * 将小端字节数组转换为整数
   * @param {Array<number>} bytes - 小端模式字节数组
   * @returns {number} - 转换后的整数
   */
  bytesToInt(bytes) {
    return bytes.reduce((acc, byte, i) => acc + (byte << (8 * i)), 0); // 按小端模式累加转换为整数
  }

  // 将十六进制字符串转换为 ArrayBuffer
  hexStringToArrayBuffer(hexString) {
    const buffer = new ArrayBuffer(hexString.length / 2);
    const dataView = new Uint8Array(buffer);
    for (let i = 0; i < hexString.length; i += 2) {
      dataView[i / 2] = parseInt(hexString.substr(i, 2), 16);
    }
    return buffer;
  }

  // 将十六进制字符串转换为字节数组
  hexStringToBytes(hexString) {
    return hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16));
  }
}
